/*
 *
 *  *    Copyright 2020-2021 luter.me
 *  *
 *  *    Licensed under the Apache License, Version 2.0 (the "License");
 *  *    you may not use this file except in compliance with the License.
 *  *    You may obtain a copy of the License at
 *  *
 *  *      http://www.apache.org/licenses/LICENSE-2.0
 *  *
 *  *    Unless required by applicable law or agreed to in writing, software
 *  *    distributed under the License is distributed on an "AS IS" BASIS,
 *  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  *    See the License for the specific language governing permissions and
 *  *    limitations under the License.
 *
 */

package com.luter.heimdall.core.token;

import java.io.Serializable;
import java.util.Collection;
import java.util.stream.Collectors;

/**
 * List 分页工具类
 *
 * @param <T> the type parameter
 * @author luter
 */
public class PageModel<T> implements Serializable {
    /**
     * The constant serialVersionUID.
     */

    private static final long serialVersionUID = -7375796379237981035L;
    /**
     * 页码
     */
    private int pageNumber;
    /**
     * 每页数量
     */
    private int pageSize;
    /**
     * 数据总数
     */
    private int total;
    /**
     * 总页数
     */
    private int totalPages;
    /**
     * 本页总数
     */
    private int itemsCount;
    /**
     * 本页数据
     */
    private Collection<T> items;

    /**
     * Instantiates a new List page.
     */
    public PageModel() {
    }


    /**
     * 根据给定的所有数据List，计算并构造分页
     *
     * @param dataList   待分页的数据 List (全部数据)
     * @param pageNumber 页码
     * @param pageSize   每页数量
     */
    public PageModel(Collection<T> dataList, int pageNumber, int pageSize) {
        if (null == dataList || dataList.isEmpty()) {
            return;
        }
        final int start = getStart(pageNumber, pageSize);
        this.total = dataList.size();
        this.items = dataList.stream()
                .skip(start)
                .limit(pageSize).collect(Collectors.toList());
        this.totalPages = this.total == 0 ? 0 : (int) Math.ceil((double) this.total / (double) pageSize);
        this.itemsCount = this.items.size();
    }

    /**
     * 初始化分页对象
     * <p>
     * 构造可以返回的结果对象
     *
     * @param pageNumber 页码
     * @param pageSize   每页数量
     * @param total      记录总数
     * @param items      本页数据
     */
    public PageModel(int pageNumber, int pageSize, int total, Collection<T> items) {
        this.total = total;
        this.totalPages = this.total == 0 ? 0 : (int) Math.ceil((double) this.total / (double) pageSize);
        this.itemsCount = items.size();
        this.items = items;
    }

    /**
     * 根据页码和每页数量计算 Start 起始记录位置
     *
     * @param pageNumber 页码
     * @param pageSize   每页数量
     * @return the start
     */
    public int getStart(int pageNumber, int pageSize) {
        if (pageNumber <= 0) {
            throw new IllegalArgumentException("invalid page number,must be greater than 0: " + pageNumber);
        }
        if (pageSize <= 0) {
            throw new IllegalArgumentException("invalid page size ,must be greater than 0: " + pageSize);
        }
        return (pageNumber - 1) * pageSize;
    }

    /**
     * Gets page number.
     *
     * @return the page number
     */
    public int getPageNumber() {
        return pageNumber;
    }

    /**
     * Sets page number.
     *
     * @param pageNumber the page number
     * @return the page number
     */
    public PageModel<T> setPageNumber(int pageNumber) {
        this.pageNumber = pageNumber;
        return this;
    }

    /**
     * Gets page size.
     *
     * @return the page size
     */
    public int getPageSize() {
        return pageSize;
    }

    /**
     * Sets page size.
     *
     * @param pageSize the page size
     * @return the page size
     */
    public PageModel<T> setPageSize(int pageSize) {
        this.pageSize = pageSize;
        return this;
    }

    /**
     * Gets total.
     *
     * @return the total
     */
    public int getTotal() {
        return total;
    }

    /**
     * Sets total.
     *
     * @param total the total
     * @return the total
     */
    public PageModel<T> setTotal(int total) {
        this.total = total;
        return this;
    }

    /**
     * Gets items count.
     *
     * @return the items count
     */
    public int getItemsCount() {
        return itemsCount;
    }

    public PageModel<T> setItemsCount(int itemsCount) {
        this.itemsCount = itemsCount;
        return this;
    }

    public Collection<T> getItems() {
        return items;
    }

    public PageModel<T> setItems(Collection<T> items) {
        this.items = items;
        return this;
    }

    /**
     * Gets total pages.
     *
     * @return the total pages
     */
    public int getTotalPages() {
        return totalPages;
    }

    /**
     * Sets total pages.
     *
     * @param totalPages the total pages
     * @return the total pages
     */
    public PageModel<T> setTotalPages(int totalPages) {
        this.totalPages = totalPages;
        return this;
    }

    @Override
    public String toString() {
        return "PageModel{" +
                "pageNumber=" + pageNumber +
                ", pageSize=" + pageSize +
                ", total=" + total +
                ", totalPages=" + totalPages +
                ", itemsCount=" + itemsCount +
                ", items=" + items +
                '}';
    }
}
